home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Comm / AmiTCP30b2.lha / src / amitcp / kern / amiga_netdb.c < prev    next >
C/C++ Source or Header  |  1994-04-06  |  25KB  |  1,006 lines

  1. RCS_ID_C="$Id: amiga_netdb.c,v 3.2 1994/04/06 15:37:29 too Exp $";
  2. /* 
  3.  * amiga_netdb.c --- NetDB Parse Functions
  4.  *
  5.  * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
  6.  *                    Helsinki University of Technology, Finland.
  7.  *                    All rights reserved.
  8.  *
  9.  * Created      : Tue Apr 27 10:18:58 1993 ppessi
  10.  * Last modified: Wed Apr  6 18:14:49 1994 too
  11.  *
  12.  * $Log: amiga_netdb.c,v $
  13.  * Revision 3.2  1994/04/06  15:37:29  too
  14.  * Added parsing of '@' as match for all private ports (# < 1024)
  15.  * in addaccessent()
  16.  *
  17.  * Revision 3.1  1994/03/26  09:41:13  too
  18.  * Added netdb parsing code for ACCESS control
  19.  *
  20.  * Revision 1.14  1993/07/28  16:00:43  jraja
  21.  * Fixed two inet_aton() calls (return value was misunderstood).
  22.  *
  23.  * Revision 1.13  1993/06/14  15:37:48  jraja
  24.  * Changed file line handling to somewhat better.
  25.  * Added check for too deep recursion of the netdb files.
  26.  *
  27.  * Revision 1.12  1993/06/13  23:39:27  jraja
  28.  * Changed HOST to use Unix compatible format.
  29.  * Added WITH to include other files.
  30.  * '#' as a comment introducer now fully supported.
  31.  * Uses parse function table instead of a switch-case structure.
  32.  * read_netdb() now supports 'prefixes'.
  33.  * read_netdb() now CD's to the AmiTCP:db before opening the file.
  34.  *
  35.  * Revision 1.11  1993/06/04  11:16:15  jraja
  36.  * Fixes for first public release.
  37.  *
  38.  * Revision 1.10  1993/05/29  20:54:12  jraja
  39.  * Changed to use _PATH_NETDB.
  40.  *
  41.  * Revision 1.9  1993/05/17  01:07:47  ppessi
  42.  * Changed RCS version.
  43.  *
  44.  * Revision 1.8  1993/05/16  19:24:03  jraja
  45.  * Changed structure names:
  46.  * NameServerNode => NameserventNode, nameserver => nameservent,
  47.  * DomainNode => DomainentNode, domainname => domainent.
  48.  *
  49.  * Revision 1.7  1993/05/16  00:48:14  jraja
  50.  * Changed init_netdb() to forgive file errors.
  51.  *
  52.  * Revision 1.6  1993/05/16  00:17:32  jraja
  53.  * Changed return values from explicit numbers to RETURN_XXXX.
  54.  * Changed syntax errors to be logged and bypassed.
  55.  * Implemented nameserver and domain parsing.
  56.  *
  57.  * Revision 1.5  93/05/14  11:37:11  11:37:11  ppessi (Pekka Pessi)
  58.  * Cleaned Arexx interface a bit. Private information removed from
  59.  * header files, added to this file.
  60.  * 
  61.  * Revision 1.4  93/05/05  16:10:10  16:10:10  puhuri (Markus Peuhkuri)
  62.  * Fixes for final demo.
  63.  * 
  64.  * Revision 1.3  93/05/04  16:53:28  16:53:28  ppessi (Pekka Pessi)
  65.  * Added net and host entry parsing.
  66.  * 
  67.  * Revision 1.2  93/05/04  12:38:32  12:38:32  jraja (Jarno Tapio Rajahalme)
  68.  * _Minor_ fixes...
  69.  * 
  70.  * Revision 1.1  93/04/28  21:56:49  21:56:49  ppessi (Pekka Pessi)
  71.  * Initial revision
  72.  * 
  73.  */
  74.  
  75. #include <conf.h>
  76.  
  77. #include <sys/param.h>
  78. #include <sys/systm.h>
  79. #include <sys/syslog.h>
  80. #include <sys/socket.h>
  81. #include <sys/malloc.h>
  82. #include <sys/mbuf.h>
  83.  
  84. #include <kern/amiga_includes.h>
  85. #include <kern/amiga_config.h>
  86. #include <kern/amiga_netdb.h>
  87. #include <kern/accesscontrol.h>
  88.  
  89. #include <netinet/in.h>
  90.  
  91. #include <dos/dos.h>
  92. #include <dos/rdargs.h>
  93.  
  94. #if __SASC
  95. #include <proto/dos.h>
  96. #elif __GNUC__
  97. #include <inline/dos.h>
  98. #else
  99. #error Your compiler is not supported in this release.
  100. #endif
  101.  
  102. int inet_aton(register const char *cp, struct in_addr *addr);
  103.  
  104. LONG read_netdb(struct NetDataBase *ndb, UBYTE *fname, const UBYTE** errstrp, struct CSource *res, int prefixindex);
  105.  
  106. /*
  107.  * Global pointer for the NetDataBase
  108.  */
  109. struct NetDataBase *NDB = NULL;
  110.  
  111. /*
  112.  * Default netdatabase name
  113.  */
  114. STRPTR netdbname = _PATH_NETDB;
  115.  
  116. /* 
  117.  * Templates for Arexx commands and DB files
  118.  */
  119. STRPTR NETDBENTRY = 
  120.   "WITH,H=HOST,N=NET,S=SERVICE,P=PROTOCOL,NS=NAMESERVER,DO=DOMAIN,ACC=ACCESS";
  121.  
  122. enum ndbtype { KNDB_WITH, KNDB_HOST, KNDB_NET, KNDB_SERV, KNDB_PROTO, 
  123.            KNDB_DNS, KNDB_DOM, KNDB_ACC };
  124.  
  125. STRPTR NETDBTEMPLATE = 
  126.   "$NAME$/A,$ENTRY$/A,$ALIAS$/M";
  127.  
  128. STRPTR PROTOCOL_TEMPLATE = 
  129.   "$NAME$/A,$NUMBER$/A/N,$ALIAS$/M";
  130.  
  131. enum ndbarg { KNDB_NAME, KNDB_DATA, KNDB_ALIAS };
  132.  
  133. #define NDBARGS 3
  134.  
  135. STRPTR ACCESS_TEMPLATE =
  136.   "$PORT$/A,$HOSTMASK$/A,$ACCESS$/A,LOG/S";
  137.  
  138. enum accarg { KACC_PORT, KACC_HOSTMASK, KACC_ACCESS, KACC_LOG };
  139.  
  140. #define ACCARGS 4
  141.  
  142. STRPTR WITH_TEMPLATE = 
  143.   "$FILE$/A,PREFIX/K";
  144. #define WITHARGS 2
  145. enum witharg { WITH_FILE, WITH_PREFIX };
  146.  
  147. /* prototypes for the netdb parsing functions */
  148.  
  149. LONG addwith(struct NetDataBase *ndb,
  150.          struct RDArgs *rdargs, UBYTE **errstrp);
  151. LONG addhostent(struct NetDataBase *ndb,
  152.         struct RDArgs *rdargs, UBYTE **errstrp);
  153. LONG addnetent(struct NetDataBase *ndb,
  154.            struct RDArgs *rdargs, UBYTE **errstrp);
  155. LONG addservent(struct NetDataBase *ndb,
  156.         struct RDArgs *rdargs, UBYTE **errstrp);
  157. LONG addprotoent(struct NetDataBase *ndb,
  158.          struct RDArgs *rdargs, UBYTE **errstrp);
  159. LONG addnameservent(struct NetDataBase *ndb,
  160.             struct RDArgs *rdargs, UBYTE **errstrp);
  161. LONG adddomainent(struct NetDataBase *ndb,
  162.           struct RDArgs *rdargs, UBYTE **errstrp);
  163. LONG addaccessent(struct NetDataBase *ndb,
  164.           struct RDArgs *rdargs, const UBYTE **errstrp);
  165. LONG addndbent(struct NetDataBase *ndb,
  166.            struct RDArgs *rdargs, UBYTE **errstrp);
  167.  
  168. typedef LONG (*ndb_parse_f)(struct NetDataBase *ndb,
  169.         struct RDArgs *rdargs, UBYTE **errstrp);
  170.  
  171. /* Array of parsing functions. Note that the order is same as in the
  172.  * NETDBENTRY.
  173.  */
  174. ndb_parse_f ndb_parse_funs[] = {
  175.   addwith,
  176.   addhostent,
  177.   addnetent,
  178.   addservent,
  179.   addprotoent,
  180.   addnameservent,
  181.   adddomainent,
  182.   addaccessent
  183. };
  184.  
  185. /*
  186.  * Alloc a NetDataBase
  187.  */
  188. struct NetDataBase *
  189. alloc_netdb(struct NetDataBase *ndb)
  190. {
  191.   if (ndb || 
  192.       (ndb = bsd_malloc(sizeof (*NDB), M_NETDB, M_WAITOK))) {  
  193.     struct MinList *gl;
  194.  
  195.     InitSemaphore(&ndb->ndb_Lock);
  196.     for (gl = (struct MinList *)&ndb->ndb_Hosts;
  197.      gl <= (struct MinList *)&ndb->ndb_Domains;        
  198.      gl++)
  199.       NewList((struct List *)gl);
  200.     
  201.   }
  202.   
  203.   ndb->ndb_AccessCount = 0;
  204.   if ((ndb->ndb_AccessTable =
  205.        bsd_malloc(TMPACTSIZE, M_NETDB, M_WAITOK)) == NULL) {
  206.     bsd_free(ndb, M_NETDB);
  207.     ndb = NULL;
  208.   }
  209.   return ndb;
  210. }
  211.  
  212. /*
  213.  * Free a NetDataBase
  214.  * Caller must have a write lock on NDB
  215.  */
  216. void
  217. free_netdb(struct NetDataBase *ndb)
  218. {
  219.   struct GenentNode *gn;
  220.   struct MinList *gl;
  221.  
  222.   for (gl = (struct MinList *)&ndb->ndb_Hosts;
  223.        gl <= (struct MinList *)&ndb->ndb_Domains;        
  224.        gl++)
  225.     while (gn = (struct GenentNode *)RemHead((struct List *)gl)) 
  226.       bsd_free(gn, M_NETDB);
  227.  
  228.   if (ndb->ndb_AccessTable != NULL) {
  229.     bsd_free(ndb->ndb_AccessTable, M_NETDB);
  230.     ndb->ndb_AccessTable = NULL;
  231.   }
  232.   bsd_free(ndb, M_NETDB);
  233. }
  234.  
  235. #ifdef DEBUG
  236. static char * zap;
  237. static size_t zap_size;
  238. #endif
  239.  
  240. /* 
  241.  * Copy alias list to ato, alias strings and name to cto
  242.  */
  243. static void
  244. aliascpy(UBYTE *cto, UBYTE *name, UBYTE**ato, UBYTE **afrom)
  245. #ifdef DEBUG
  246.   UBYTE *logname = name;
  247. #endif
  248.   do {
  249.     while(*cto++ = *name++);
  250.   } while (afrom && (name = *afrom++) && (*ato++ = cto));
  251.  
  252.   *ato = NULL;
  253.  
  254. #ifdef DEBUG
  255.   if (cto != zap + zap_size) {
  256.     log(LOG_ERR, "%s: mismatch in size %ld != expected %ld\n",
  257.     logname, cto - zap, zap_size);
  258.   } 
  259. #endif
  260. }
  261.  
  262. /*
  263.  * Allocate a netdb node
  264.  *
  265.  * nodesize is the size of the base structure, additional space
  266.  * is allocated for the name and the aliases.
  267.  * alias is NULL terminated array of alias name pointers.
  268.  * Number of aliases is returned via aliasp.
  269.  *
  270.  * size field of the allocated node is set to the total size - size for 
  271.  * the MinNode and the size field itself.
  272.  */
  273. static void *
  274. node_alloc(size_t nodesize, UBYTE *name, UBYTE **alias, int *aliasp)
  275. {
  276.   struct GenentNode *gn;
  277.  
  278.   nodesize += strlen(name) + 1;    /* Add space needed for the name */
  279.  
  280.   *aliasp = 1;
  281.   nodesize += sizeof (char*);    /* Alias list NULL terminator */
  282.  
  283.   /* Calculate the size of the aliases */
  284.   if (alias) {
  285.     while (*alias) {
  286.       (*aliasp)++;
  287.       nodesize += strlen(*alias++) + 1 + sizeof (char*);
  288.     }
  289.   }
  290.   gn = bsd_malloc(nodesize, M_NETDB, M_WAITOK);
  291.   /*
  292.    * set the ent size
  293.    */
  294.   if (gn)
  295.     gn->gn_EntSize = nodesize - sizeof (struct GenentNode);
  296.  
  297. #ifdef DEBUG  
  298.   zap_size = nodesize;
  299.   zap = (char *)gn;
  300. #endif
  301.   return gn;
  302. }
  303.  
  304. /*
  305.  * Parse a service entry.
  306.  */
  307. LONG
  308. addwith(struct NetDataBase *ndb,
  309.     struct RDArgs *rdargs,
  310.     UBYTE **errstrp)
  311. {
  312.   UBYTE result[REPLYBUFLEN + 1];
  313.   struct CSource res;
  314.   LONG retval = RETURN_OK;
  315.   LONG Args[WITHARGS] = { 0 };
  316.   int which;
  317.  
  318.   res.CS_Buffer = result; 
  319.   res.CS_Length = sizeof (result);
  320.   res.CS_CurChr = 0;
  321.  
  322.   if (rdargs = ReadArgs(WITH_TEMPLATE, Args, rdargs)) {
  323.     if (Args[WITH_PREFIX] == 0)    /* no prefix given */
  324.       which = -1;
  325.     else {
  326.       /* match given prefix */
  327.       which = FindArg(NETDBENTRY, (UBYTE *)Args[WITH_PREFIX]);
  328.       if (which < 0) {
  329.     *errstrp = ERR_VALUE;
  330.     retval = RETURN_WARN;
  331.       }
  332.     }
  333.     if (retval == RETURN_OK) {
  334.  
  335.       retval = read_netdb(ndb, (UBYTE *)Args[WITH_FILE], errstrp, &res, 
  336.               which);
  337.  
  338.       if (retval) {
  339.     log(LOG_WARNING, "netdb: WITH file %s: %s", 
  340.         (UBYTE *)Args[WITH_FILE], *errstrp);
  341. #if 0
  342.     if (retval <= RETURN_ERROR)
  343.       retval = RETURN_OK;    /* forgive */
  344. #endif    
  345.       }
  346.     }
  347.     FreeArgs(rdargs);
  348.   } else {
  349.     *errstrp = ERR_SYNTAX; retval = RETURN_WARN;
  350.   }
  351.   return retval;
  352. }
  353.  
  354. /*
  355.  * Parse a service entry.
  356.  */
  357. LONG
  358. addservent(struct NetDataBase *ndb,
  359.         struct RDArgs *rdargs,
  360.         UBYTE **errstrp)
  361. {
  362.   LONG retval;
  363.   LONG Args[NDBARGS] = { 0 };
  364.   struct ServentNode *sn;     
  365.   int aliases, plen;
  366.  
  367.   if (rdargs = ReadArgs(NETDBTEMPLATE, Args, rdargs)) {
  368.     /* convert port number */
  369.     UBYTE *s_proto = (UBYTE*)Args[KNDB_DATA];
  370.     if ((plen = StrToLong(s_proto, &Args[KNDB_DATA])) > 0 &&
  371.     s_proto[plen++] == '/') {
  372.       int protonamelen = strlen(s_proto = s_proto + plen) + 1;
  373.       sn = node_alloc(sizeof (*sn) + protonamelen,
  374.               (UBYTE*)Args[KNDB_NAME], 
  375.               (UBYTE **)Args[KNDB_ALIAS], &aliases);
  376.       if (sn) {
  377.     UBYTE **alias = (UBYTE **)(sn+1);
  378.     UBYTE *name = (UBYTE *)(alias + aliases);
  379.  
  380.     sn->sn_Ent.s_port = Args[KNDB_DATA];
  381.     sn->sn_Ent.s_proto = strcpy(name, s_proto);
  382.     sn->sn_Ent.s_name = name + protonamelen;
  383.     sn->sn_Ent.s_aliases = (char **)alias;
  384.  
  385.     /* Copy aliases */
  386.     aliascpy(sn->sn_Ent.s_name, (UBYTE*)Args[KNDB_NAME], 
  387.          alias, (UBYTE **)Args[KNDB_ALIAS]);
  388.     AddTail((struct List*)&ndb->ndb_Services, (struct Node*)sn);
  389.     retval = RETURN_OK;
  390.       } else {
  391.     *errstrp = ERR_MEMORY; retval = RETURN_FAIL;
  392.       }
  393.     } else { 
  394.       *errstrp = ERR_VALUE; retval = RETURN_WARN; 
  395.     } 
  396.     FreeArgs(rdargs);
  397.   } else {
  398.     *errstrp = ERR_SYNTAX; retval = RETURN_WARN;
  399.   }
  400.   return retval;
  401. }
  402.  
  403. /*
  404.  * Parse a host entry.
  405.  *
  406.  * NOTE: The host entry has the address in the 'name' and the official name
  407.  * in the 'data'.
  408.  */
  409. LONG
  410. addhostent(struct NetDataBase *ndb,
  411.         struct RDArgs *rdargs,
  412.         UBYTE **errstrp)
  413. {
  414.   LONG retval;
  415.   LONG Args[NDBARGS] = { 0 };
  416.   struct HostentNode *hn;
  417.   struct in_addr addr;
  418.   int aliases;
  419.  
  420.   if (rdargs = ReadArgs(NETDBTEMPLATE, Args, rdargs)) {
  421.     /* convert ip address */
  422.     if (inet_aton((char*)Args[KNDB_NAME], &addr)) {
  423.       hn = node_alloc(sizeof (*hn) + 2*sizeof (&addr) + sizeof (addr),
  424.               (UBYTE*)Args[KNDB_DATA], 
  425.               (UBYTE **)Args[KNDB_ALIAS], &aliases);
  426.       if (hn) {
  427.     struct in_addr **addrtbl = (struct in_addr **)(hn + 1);
  428.     UBYTE **alias = (UBYTE **)((UBYTE*)(addrtbl + 2) + sizeof (addr));
  429.     UBYTE *name = (UBYTE *)(alias + aliases);
  430.  
  431.     hn->hn_Ent.h_addrtype = AF_INET;
  432.     hn->hn_Ent.h_length = sizeof (addr);
  433.     hn->hn_Ent.h_addr_list = (char **)addrtbl;
  434.     hn->hn_Ent.h_name = name;
  435.     hn->hn_Ent.h_aliases = (char **)alias;
  436.  
  437.     /* Make address list */
  438.     addrtbl[0] = (struct in_addr *)(addrtbl + 2);
  439.     addrtbl[1] = NULL;
  440.     bcopy(&addr, addrtbl[0], sizeof (addr));
  441.  
  442.     /* Copy aliases */
  443.     aliascpy(hn->hn_Ent.h_name, (UBYTE*)Args[KNDB_DATA], 
  444.          alias, (UBYTE **)Args[KNDB_ALIAS]);
  445.     AddTail((struct List*)&ndb->ndb_Hosts, (struct Node*)hn);
  446.     retval = RETURN_OK;
  447.       } else {
  448.     *errstrp = ERR_MEMORY; retval = RETURN_FAIL;
  449.       }
  450.     } else { 
  451.       *errstrp = ERR_VALUE; retval = RETURN_WARN; 
  452.     } 
  453.     FreeArgs(rdargs);
  454.   } else {
  455.     *errstrp = ERR_SYNTAX; retval = RETURN_WARN;
  456.   }
  457.   return retval;
  458. }
  459.  
  460. /*
  461.  * Parse a net entry.
  462.  */
  463. LONG
  464. addnetent(struct NetDataBase *ndb,
  465.       struct RDArgs *rdargs,
  466.       UBYTE **errstrp)
  467. {
  468.   LONG retval;
  469.   LONG Args[NDBARGS] = { 0 };
  470.   struct NetentNode *nn;
  471.   struct in_addr addr;
  472.   int aliases;
  473.  
  474.   if (rdargs = ReadArgs(NETDBTEMPLATE, Args, rdargs)) {
  475.     /* convert ip address */
  476.     if (inet_aton((char*)Args[KNDB_DATA], &addr)) {
  477.       nn = node_alloc(sizeof (*nn),
  478.               (UBYTE*)Args[KNDB_NAME], 
  479.               (UBYTE **)Args[KNDB_ALIAS], &aliases);
  480.       if (nn) {
  481.     UBYTE **alias = (UBYTE **)(nn + 1);
  482.     UBYTE *name = (UBYTE *)(alias + aliases);
  483.  
  484.     nn->nn_Ent.n_addrtype = AF_INET;
  485.     nn->nn_Ent.n_name = name;
  486.     nn->nn_Ent.n_aliases = (char **)alias;
  487.     bcopy(&addr, &nn->nn_Ent.n_net, sizeof (unsigned long));
  488.  
  489.     /* Copy aliases */
  490.     aliascpy(nn->nn_Ent.n_name, (UBYTE*)Args[KNDB_NAME], 
  491.          alias, (UBYTE **)Args[KNDB_ALIAS]);
  492.     AddTail((struct List*)&ndb->ndb_Networks, (struct Node*)nn);
  493.     retval = RETURN_OK;
  494.       } else {
  495.     *errstrp = ERR_MEMORY; retval = RETURN_FAIL;
  496.       }
  497.     } else { 
  498.       *errstrp = ERR_VALUE; retval = RETURN_WARN;
  499.     } 
  500.     FreeArgs(rdargs);
  501.   } else {
  502.     *errstrp = ERR_SYNTAX; retval = RETURN_WARN;
  503.   }
  504.   return retval;
  505. }
  506.  
  507. /*
  508.  * Parse a protocol entry.
  509.  */
  510. LONG
  511. addprotoent(struct NetDataBase *ndb,
  512.         struct RDArgs *rdargs,
  513.         UBYTE **errstrp)
  514. {
  515.   LONG retval;
  516.   LONG Args[NDBARGS] = { 0 };
  517.   struct ProtoentNode *pn;     
  518.   int aliases;
  519.  
  520.   if (rdargs = ReadArgs(PROTOCOL_TEMPLATE, Args, rdargs)) {
  521.     
  522.     if (Args[KNDB_DATA]) {
  523.       pn = node_alloc(sizeof (*pn), (UBYTE*)Args[KNDB_NAME], 
  524.               (UBYTE **)Args[KNDB_ALIAS], &aliases);
  525.       if (pn) {
  526.     UBYTE **alias = (UBYTE **)(pn+1);
  527.     UBYTE *name = (UBYTE *)(alias + aliases);
  528.  
  529.     pn->pn_Ent.p_name = name;
  530.     pn->pn_Ent.p_aliases = (char **)alias;
  531.     pn->pn_Ent.p_proto = *(LONG *)Args[KNDB_DATA];
  532.  
  533.     /* Copy name and aliases */
  534.     aliascpy(name, (UBYTE*)Args[KNDB_NAME], 
  535.          alias, (UBYTE **)Args[KNDB_ALIAS]);
  536.     AddTail((struct List*)&ndb->ndb_Protocols, (struct Node*)pn);
  537.     retval = RETURN_OK;
  538.       } else {
  539.     *errstrp = ERR_MEMORY; retval = RETURN_FAIL;
  540.       }
  541.     } else { 
  542.       *errstrp = ERR_VALUE; retval = RETURN_WARN; 
  543.     } 
  544.     FreeArgs(rdargs);
  545.   } else {
  546.     *errstrp = ERR_SYNTAX; retval = RETURN_WARN;
  547.   }
  548.   return retval;
  549. }
  550.  
  551. /*
  552.  * Parse a Name Server entry
  553.  */
  554. LONG
  555. addnameservent(struct NetDataBase *ndb,
  556.            struct RDArgs *rdargs,
  557.            UBYTE **errstrp)
  558. {
  559.   UBYTE Buffer[KEYWORDLEN];
  560.   LONG  BufLen = sizeof (Buffer);
  561.   struct in_addr ns_addr;
  562.   struct NameserventNode *nsn;
  563.  
  564.   if (ReadItem(Buffer, BufLen, &rdargs->RDA_Source) <= 0) {
  565.     *errstrp = ERR_SYNTAX; 
  566.     return RETURN_WARN;
  567.   }
  568.   if (!inet_aton(Buffer, &ns_addr)) {
  569.     *errstrp = ERR_VALUE;
  570.     return RETURN_WARN; 
  571.   }
  572.   if ((nsn = bsd_malloc(sizeof (*nsn), M_NETDB, M_WAITOK)) == NULL) {
  573.     *errstrp = ERR_MEMORY;
  574.     return RETURN_FAIL;
  575.   }
  576.   nsn->nsn_EntSize = sizeof (nsn->nsn_Ent);
  577.   nsn->nsn_Ent.ns_addr = ns_addr;
  578.   
  579.   AddTail((struct List*)&ndb->ndb_NameServers, (struct Node*)nsn);
  580.   return RETURN_OK;
  581. }
  582.  
  583. /*
  584.  * Parse a Domain Name entry
  585.  */
  586. LONG
  587. adddomainent(struct NetDataBase *ndb,
  588.            struct RDArgs *rdargs,
  589.            UBYTE **errstrp)
  590. {
  591.   UBYTE Buffer[REPLYBUFLEN];
  592.   LONG  BufLen = sizeof (Buffer);
  593.   struct DomainentNode *dn;
  594.   short  nodesize;
  595.  
  596.   if (ReadItem(Buffer, BufLen, &rdargs->RDA_Source) <= 0) {
  597.     *errstrp = ERR_SYNTAX; 
  598.     return RETURN_WARN;
  599.   }
  600.   nodesize = sizeof (*dn) + strlen(Buffer) + 1;
  601.   if ((dn = bsd_malloc(nodesize, M_NETDB, M_WAITOK)) == NULL) {
  602.     *errstrp = ERR_MEMORY;
  603.     return RETURN_FAIL;
  604.   }
  605.   dn->dn_EntSize = nodesize - sizeof (struct GenentNode);
  606.   dn->dn_Ent.d_name = (char *)(dn + 1);
  607.   
  608.   strcpy((char *)(dn + 1), Buffer);
  609.  
  610.   AddTail((struct List*)&ndb->ndb_Domains, (struct Node*)dn);
  611.   return RETURN_OK;
  612. }
  613.  
  614. /*
  615.  * Parse a access control entry.. after reading the whole netdatabase
  616.  * access list must be reorganized;
  617.  */
  618. LONG
  619. addaccessent(struct NetDataBase *ndb,
  620.          struct RDArgs *rdargs,
  621.          const UBYTE **errstrp)
  622. {
  623.   LONG retval = RETURN_WARN;
  624.   LONG Args[ACCARGS] = { 0 };
  625.  
  626.   ULONG host, mask;
  627.   UWORD port, flags = ACF_CONTINUE;
  628.  
  629.   if (ndb->ndb_AccessCount >= TMPACTSIZE / sizeof (struct AccessItem)) {
  630.     *errstrp = "Too many access control items\n";
  631.     return retval; /* copy propagation expected */
  632.   }
  633.   
  634.   if ((rdargs = ReadArgs(ACCESS_TEMPLATE, Args, rdargs)) != NULL) {
  635.     
  636.     if (strcmp((char *)Args[KACC_PORT], "*") == 0)
  637.       port = 0;
  638.     else if (strcmp((char *)Args[KACC_PORT], "@") == 0) {
  639.       port = 0; flags |= ACF_PRIVONLY;
  640.     }
  641.     else if (StrToLong((char *)Args[KACC_PORT], (LONG *)&host) > 0
  642.          && host != 0) {
  643.       if (host > 0xffff) {
  644.     *errstrp = "Illegal port value\n";
  645.     goto exit;
  646.       }
  647.       port = host;
  648.     }
  649.     else {
  650.       struct ServentNode * entNode;
  651.  
  652.       if ((entNode =
  653.        findServentNode(ndb, (char *)Args[KACC_PORT], "tcp")) != NULL)
  654.       port = entNode->sn_Ent.s_port;
  655.       else {
  656.     *errstrp = "Illegal port value\n";
  657.     goto exit;
  658.       }
  659.     }
  660.     {
  661.       int zmask = 0xFFFFFFFF;
  662.       int i = 0, ls = 0, dots = 0;
  663.  
  664. #define hm ((char *)Args[KACC_HOSTMASK])
  665.       
  666.       while ((hm[i] >= '0' && hm[i] <= '9') || hm[i] == '.' || hm[i] == '*') {
  667.     if (hm[i] == '.') {
  668.       ls = 0;
  669.       dots++;
  670.     }
  671.     else if (hm[i] == '*') {
  672.       hm[i] = '0';
  673.       ls = 1;
  674.       zmask ^= (0xFF000000 >> 8 * dots);
  675.     }
  676.     i++;
  677.       }
  678.       if (ls == 1)
  679.     while (dots++ < 3)
  680.       zmask ^= (0xFF000000 >> 8 * dots);
  681.  
  682.       if (hm[i] == '/') {
  683.     hm[i++] = '\0';
  684.     if (inet_aton(&hm[i], (struct in_addr *)&mask) == 0) {
  685.       *errstrp = "Illegal mask value\n";
  686.       goto exit;
  687.     }
  688.       }
  689.       else
  690.     mask = 0xffffffff;
  691.  
  692.       mask &= zmask;
  693.       
  694.       if (inet_aton(hm, (struct in_addr *)&host) == 0) {
  695.     *errstrp = "Illegal host value\n";
  696.     goto exit;
  697.       }
  698. #undef hm      
  699.     }
  700.     if (strcmp((char *)Args[KACC_ACCESS], "allow") == 0)
  701.       flags |= ACF_ALLOW;
  702.     else if (strcmp((char *)Args[KACC_ACCESS], "deny") != 0) {
  703.       *errstrp = "Illegal access value\n";
  704.       goto exit;
  705.     }
  706.  
  707.     if (Args[KACC_LOG])
  708.       flags |= ACF_LOG;
  709.     
  710.     ndb->ndb_AccessTable[ndb->ndb_AccessCount].ai_port = port;
  711.     ndb->ndb_AccessTable[ndb->ndb_AccessCount].ai_host = host;
  712.     ndb->ndb_AccessTable[ndb->ndb_AccessCount].ai_mask = mask;
  713.     ndb->ndb_AccessTable[ndb->ndb_AccessCount].ai_flags = flags;
  714.     ndb->ndb_AccessCount++;
  715.  
  716.     retval = 0;
  717.   exit:
  718.     FreeArgs(rdargs);
  719.   }
  720.   else
  721.     *errstrp = ERR_SYNTAX;
  722.  
  723.   return retval;
  724. }
  725.  
  726. /*
  727.  * Add an entry into NetDB. 
  728.  * Caller must have a write lock on ndb 
  729.  */
  730. LONG 
  731. addndbent(struct NetDataBase *ndb,
  732.       struct RDArgs *rdargs, 
  733.       UBYTE **errstrp)
  734. {
  735.   if (NDB) {
  736.     LONG item;
  737.     enum ndbtype which;
  738.     UBYTE Buffer[KEYWORDLEN];
  739.  
  740.     /* Get entry type */
  741.     item = ReadItem(Buffer, sizeof (Buffer), &rdargs->RDA_Source);
  742.  
  743.     if (item == 0)
  744.       return RETURN_OK;        /* empty line */
  745.     if (item < 0) {
  746.       *errstrp = ERR_SYNTAX;
  747.       return RETURN_WARN;
  748.     }
  749.     if ((which = FindArg(NETDBENTRY, Buffer)) < 0) {
  750.       *errstrp = ERR_UNKNOWN;
  751.       return RETURN_WARN;
  752.     } 
  753.  
  754.     return ndb_parse_funs[which](ndb, rdargs, errstrp);
  755.  
  756.   } else {
  757.     *errstrp = ERR_NONETDB;
  758.     return RETURN_FAIL;
  759.   }
  760. }
  761.  
  762. /* 
  763.  * Read in a NetDataBase file
  764.  */
  765. LONG 
  766. read_netdb(struct NetDataBase *ndb, UBYTE *fname, 
  767.       const UBYTE** errstrp, struct CSource *res, int prefixindex)
  768. {
  769.   LONG warnval = RETURN_OK;
  770.   LONG retval = RETURN_OK, ioerr = 0;
  771.   UBYTE *p, *buf = AllocMem(CONFIGLINELEN, MEMF_PUBLIC);
  772.   struct RDArgs *rdargs;
  773.   BPTR fh;
  774.   short line = 0;
  775.   ndb_parse_f parser;
  776.   BPTR lock, oldcd;
  777.  
  778.   /* Get an exclusive lock on the database.
  779.    * Multiple locks are OK (when this function is called recursively)
  780.    */
  781.   LOCK_W_NDB(ndb);        
  782.   if (ndb->ndb_Lock.ss_NestCount > 10) {
  783.     UNLOCK_NDB(ndb);
  784.     *errstrp = "Too many files included";
  785.     return RETURN_ERROR;
  786.   }
  787.   if (buf) {
  788.  
  789.     /* CD to netdb directory */
  790.     lock = Lock(_PATH_DB, ACCESS_READ);
  791.     if (lock)
  792.       oldcd = CurrentDir(lock);
  793.     
  794.     if (fh = Open(fname, MODE_OLDFILE)) {
  795.       if (rdargs = AllocDosObject(DOS_RDARGS, NULL)) {
  796.     /* initialize CSource of the rdargs */
  797.     rdargs->RDA_Source.CS_Buffer = buf;
  798.     /* initialize rest fields (see dos/rdargs.h) */
  799.     rdargs->RDA_DAList = NULL;
  800.     rdargs->RDA_ExtHelp = NULL;
  801.     rdargs->RDA_Flags = 0;
  802.     
  803.     if (prefixindex < 0)
  804.       parser = addndbent;    /* no prefix */
  805.     else
  806.       parser = ndb_parse_funs[prefixindex];
  807.     
  808.     while (FGets(fh, buf, CONFIGLINELEN - 1)) {
  809.       line++;        /* maintain line number */
  810.       /* pass by white space */
  811.       for (p = buf; *p == ' ' || *p == '\t' || *p == '\r'; p++)
  812.         ;
  813.       rdargs->RDA_Source.CS_CurChr = p - buf;
  814.       if (*p == '#' || *p == ';' || *p == '\n') /* only a comment line */
  815.         continue;
  816.       /* remove comments & calc length */
  817.       for (; *p; p++) { 
  818.         if (*p == '#' || *p == ';') {
  819.           *p++ = '\n';
  820.           *p   = '\0';    /* terminate line */
  821.           break;
  822.         }
  823.       }
  824.       /* ensure that line ends with '\n' (ReadArgs() depends on it) */
  825.       if (*(p - 1) != '\n') {
  826.         *p++ = '\n';
  827.         *p   = '\0';
  828.       }
  829.       rdargs->RDA_Source.CS_Length = p - buf;
  830.       rdargs->RDA_Buffer = NULL;
  831.       rdargs->RDA_BufSiz = 0;
  832.       retval = parser(ndb, rdargs, errstrp);
  833.       if (retval == RETURN_OK)
  834.         continue;
  835.       if (retval != RETURN_WARN) /* severe error */
  836.         break;
  837.       
  838.       /* Log the error */
  839.       log(LOG_NOTICE, "NetDB(%s) line %ld: %s before col %ld\n",
  840.           fname, line, *errstrp, rdargs->RDA_Source.CS_CurChr);
  841.  
  842.       warnval = retval;
  843.     }
  844.     /* Check file error */ 
  845.     ioerr = IoErr();
  846.     
  847.     FreeDosObject(DOS_RDARGS, rdargs);
  848.       }
  849.       Close(fh);
  850.     } else {
  851.       ioerr = IoErr();
  852.     }
  853.     
  854.     if (ioerr) {
  855.       Fault(ioerr, "readnetdb", res->CS_Buffer, res->CS_Length);
  856.       *errstrp = res->CS_Buffer;
  857.       retval = RETURN_ERROR;
  858.     }
  859.     
  860.     /* return old current directory */
  861.     if (lock) {
  862.       CurrentDir(oldcd);
  863.       UnLock(lock);
  864.     }
  865.  
  866.     FreeMem(buf, CONFIGLINELEN);
  867.   } else {
  868.     *errstrp = ERR_MEMORY;
  869.     retval = RETURN_FAIL;
  870.   }
  871.  
  872.   UNLOCK_NDB(ndb);
  873.  
  874.   return retval > warnval? retval: warnval;
  875. }
  876.  
  877. /*
  878.  * Parse the 'ADD' command
  879.  */
  880. LONG
  881. do_netdb(struct CSource *csarg, UBYTE **errstrp, struct CSource *res)
  882. {
  883.   struct RDArgs *rdargs;
  884.   LONG retval;
  885.   
  886.   if (rdargs = AllocDosObject(DOS_RDARGS, NULL)) {
  887.     /* initialize CSource of the rdargs */
  888.     rdargs->RDA_Source = *csarg;
  889.     /* initialize rest fields (see <dos/rdargs.h>) */
  890.     rdargs->RDA_DAList = NULL;
  891.     rdargs->RDA_Buffer = NULL;
  892.     rdargs->RDA_BufSiz = 0;
  893.     rdargs->RDA_ExtHelp = NULL;
  894.     rdargs->RDA_Flags = 0;
  895.  
  896.     LOCK_W_NDB(NDB);
  897.  
  898.     retval = addndbent(NDB, rdargs, errstrp);
  899.  
  900.     UNLOCK_NDB(NDB);
  901.     
  902.     FreeDosObject(DOS_RDARGS, rdargs);
  903.   }
  904.   else 
  905.     retval = RETURN_FAIL;
  906.     
  907.   return retval;
  908. }
  909.  
  910. /*
  911.  * Initialize the Network Data Base
  912.  */
  913. LONG 
  914. init_netdb(void)
  915. {
  916.   UBYTE result[REPLYBUFLEN + 1]; /* for error returns */
  917.   struct CSource res;
  918.   UBYTE *errstr;
  919.   LONG   retval;
  920.  
  921.   res.CS_Buffer = result;      
  922.   res.CS_Length = sizeof (result); 
  923.   res.CS_CurChr = 0;
  924.   
  925.   /* Allocate the NetDataBase */
  926.   if (!(NDB = alloc_netdb(NULL))) {
  927.     return RETURN_FAIL;
  928.   }
  929.  
  930.   /* Read in the default data base file */
  931.   retval = read_netdb(NDB, netdbname, &errstr, &res, -1);
  932.   if (retval)
  933.     log(LOG_WARNING, "init_netdb: file %s: %s", netdbname, errstr);
  934.   else
  935.     setup_accesscontroltable(NDB);
  936.  
  937.   return retval;
  938. }
  939.  
  940.  
  941. void netdb_deinit(void)
  942. {
  943.   /* A Placeholder for possible future deinitializations */
  944. }
  945.   
  946. /*
  947.  * Reset the NetDataBase
  948.  */
  949. LONG reset_netdb(struct CSource *cs,
  950.          UBYTE **errstrp,
  951.          struct CSource *res)
  952. {
  953.   LONG retval;
  954.   struct NetDataBase *newnetdb;
  955.  
  956.   /* Allocate a temporary NetDataBase */
  957.   if (!(newnetdb = alloc_netdb(NULL))) {
  958.     *errstrp = ERR_MEMORY;
  959.     return RETURN_FAIL;
  960.   }
  961.  
  962.   retval = read_netdb(newnetdb, netdbname, errstrp, res, -1);
  963.  
  964.   if (retval == RETURN_OK) {
  965.     /*
  966.      * Success
  967.      */
  968.     struct MinList *gl, *ol;
  969.  
  970.     setup_accesscontroltable(NDB);
  971.  
  972.     /* Now clear the old lists of the NDB */
  973.     LOCK_W_NDB(NDB);
  974.     free_netdb(NDB);
  975.  
  976.     /*
  977.      * Transfer the lists of the new (temporary) database
  978.      * to the NDB.
  979.      */
  980.     for (gl = (struct MinList *)&newnetdb->ndb_Hosts,
  981.      ol = (struct MinList *)&NDB->ndb_Hosts;
  982.      gl <= (struct MinList *)&newnetdb->ndb_Domains;        
  983.      gl++, ol++) {
  984.       if (gl->mlh_Head->mln_Succ) {
  985.     /* There is a non-empty list */
  986.         *ol = *gl;
  987.     ol->mlh_Head->mln_Pred = (struct MinNode*)&ol->mlh_Head;
  988.     ol->mlh_TailPred->mln_Succ = (struct MinNode*)&ol->mlh_Tail;
  989.       }
  990.     }
  991.     NDB->ndb_AccessTable = newnetdb->ndb_AccessTable;
  992.     /*
  993.      * Perhaps ugly...
  994.      */
  995.     newnetdb->ndb_AccessTable = NULL; 
  996.  
  997.     UNLOCK_NDB(NDB);
  998.   } else {
  999.     free_netdb(newnetdb);
  1000.   }
  1001.  
  1002.   bsd_free(newnetdb, M_NETDB);    /* free the temporary database */
  1003.   return retval;
  1004. }
  1005.